using System;
using System.Collections.Generic;
using System.Diagnostics;
using Behaving;
using Behaving.Actions;
using Behaving.Composites;
using CrowdPleaser.Core.Utilities;
using NUnit.Framework;

namespace Behaving.Tests
{
    [TestFixture]
    [Ignore]
    public class PerformanceTests
    {
        [Test]
        [Repeat(4)]
        public void Run_multiple_agent_updates()
        {
            Console.WriteLine("************* (remember to run in release)");

            const int numberOfAgents = 10000;
            const int numberOfUpdates = 60;
            List<TestAgent> testAgents = new List<TestAgent>();

            Looper.For(() => testAgents.Add(new TestAgent { BehaviourTree = CreateBehaviourTree() }), numberOfAgents);

            Stopwatch stopwatch = Stopwatch.StartNew();

            for (int update = 0; update < numberOfUpdates; update++)
            {
                foreach (TestAgent testAgent in testAgents)
                {
                    testAgent.BehaviourTree.Tick();
                }
            }

            Console.WriteLine("Ran {0} updates on {1} agents ({2} update in total) in {3} ms", numberOfUpdates, numberOfAgents, numberOfUpdates * numberOfAgents, stopwatch.ElapsedMilliseconds);
        }

        private static BehaviourTree CreateBehaviourTree()
        {
            BehaviourTree behaviourTree = new BehaviourTree();
            var selector = new PriortySelector();
            behaviourTree.Root = selector;
            Looper.For(() => selector.AddChild(new Conditional(() => true, new FailAction())), 10);
            selector.Children.Insert(5, new ActionBehaviour(() => RunningState.Running));
            return behaviourTree;
        }

        public class TestAgent
        {
            public TestAgent()
            {
                Id = NextId++;
            }
            public static int NextId { get; set; }
            public static TestAgent Current { get; set; }
            public int Id { get; set; }
            public BehaviourTree BehaviourTree { get; set; }
        }
    }
}